﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Clojure;
using PBMessage;
public class ActionFuncDefine 
{
    public static List<ASTNode> EvalArgs(List<ASTNode> args, Context context) 
    {
        for (int i = 0; i < args.Count;i++ ) 
        {
            args[i] = RT.Evaluate(args[i],context);
        }
        return args;
    }
    public static void Define() 
    {
        Context context = GameTrigger.Instance.ClojureContext;
        //Core
        context.Define("vec3",new FunctionNode(_Vec3));
        context.Define("create-starting-units", new FunctionNode(_Create_Start_Units));
        context.Define("findG",new FunctionNode(_findG));
        context.Define("gameobject-attr", new FunctionNode(gameobject_attr));
        //Core-Color
        context.Define("color", new FunctionNode(_Color));
        context.Define("color-red", new ObjectNode(new Color(1, 0, 0)));
        context.Define("color-white", new ObjectNode(new Color(1, 1, 1)));
        context.Define("color-green", new ObjectNode(new Color(0, 1, 0)));    
        //Actor
        context.Define("set-actor-pos", new FunctionNode(_set_actor_pos));
        context.Define("play-anim", new FunctionNode(_player_anim));
        context.Define("actor-attr",new FunctionNode(_actor_attr));
        //GamePlayer
        context.Define("unit-player-name", new FunctionNode(_UnitPlayerName));
        context.Define("unit-player",new FunctionNode(_get_unit_player));
        context.Define("localplayer", new FunctionNode(_localPlayer));
        context.Define("player-main-unit", new FunctionNode(_player_main_unit));
        context.Define("player-camp", new FunctionNode(player_Camp));
        //Unit
         context.Define("lock-camera-to-unit", new FunctionNode(_lock_camera_to_unit));
         context.Define("unit-attr",new FunctionNode(_unit_attr));
         context.Define("unit-flag", new FunctionNode(_unit_flag));
         context.Define("trigger-unit", new FunctionNode(_trigger_unit));
         context.Define("move-unit",new FunctionNode(_move_unit));
         context.Define("revive-unit",new FunctionNode(_revive_unit));
        //////////NGUI/////////////////////
        //Label
        context.Define("set-label-text",new FunctionNode(_set_label_text));
        context.Define("set-label-color",new FunctionNode(_set_label_color));
       //Sprite
        context.Define("sprite-attr",new FunctionNode(_sprite_attr));

        TriggerVars.DefineVarActions(context);
    }
    #region GameObject
    public static ASTNode gameobject_attr(List<ASTNode> args, Context context) 
    {
        args = EvalArgs(args,context);
        GameObject G = (GameObject)((ObjectNode)args[0]).Val;
        string attrType =((StringNode)args[1]).Val;
        switch (attrType) 
        {
            case "active":
              G.SetActive( ((BoolNode)args[2]).Val );
            break;
        }
        return null;
    }
    #endregion

    public static ASTNode player_Camp(List<ASTNode> args, Context context) 
    {
        args = EvalArgs(args, context);
        GamePlayer player = (GamePlayer)((ObjectNode)args[0]).Val;
        NumberNode number = new NumberNode();
        number.NumberVal = player.Camp;
        number.Type = NumberNode.NumberType.INT;
        return number;
    }

    public static ASTNode _get_unit_player(List<ASTNode> args, Context context) 
    {
        args = EvalArgs(args, context);
        Unit unit = (Unit)((ObjectNode)args[0]).Val;
        return new ObjectNode(Game.Scene.Cur<GameScene>().GamePlayers[unit.GamePlayerId]);
    }

    public static ASTNode _Vec3(List<ASTNode> args, Context context)
    {
        float X =(float)((NumberNode)args[0]).NumberVal;
        float Y = (float)((NumberNode)args[1]).NumberVal;
        float Z = (float)((NumberNode)args[2]).NumberVal;
        Vector3 vec = new Vector3(X,Y,Z);
        return new ObjectNode(vec);
    }

    public static ASTNode _Color(List<ASTNode> args, Context context) 
    {
        args = EvalArgs(args,context);
        Color color = new Color();
        color.r = (float)((NumberNode)args[0]).NumberVal;
        color.g = (float)((NumberNode)args[1]).NumberVal;
        color.b = (float)((NumberNode)args[2]).NumberVal;
        if (args.Count == 4)
        {
            color.a = (float)((NumberNode)args[3]).NumberVal;
        }
        return new ObjectNode(color);
    }

    public static ASTNode _Create_Start_Units(List<ASTNode> args, Context context) 
    {
        GameScene scene = Game.Scene.Cur<GameScene>();
        createUnitsByCamp(0,scene.ReadyPlayClamp0);
        createUnitsByCamp(scene.ReadyPlayClamp0.Count,scene.ReadyPlayClamp1);

        foreach (KeyValuePair<string, Unit> item in UnitManager.Instance.Units) 
        {
            item.Value.Init();
        }
        return null;
    }
    static void createUnitsByCamp(int addId,List<ReadRoomPlayer> lst)
    {   
        PlayerModel playerModel = Game.Model.Get<PlayerModel>();
        for (int i = 0; i < lst.Count; i++)
        {
            ReadRoomPlayer readyPlayer = lst[i];
            GamePlayer player = new GamePlayer(addId+i, readyPlayer.UserName);

            Game.Scene.Cur<GameScene>().GamePlayers.Add(player);
            player.Camp = readyPlayer.Camp;
            Unit unit = UnitManager.Instance.CreateUnit(readyPlayer.SelectId, readyPlayer.UserName, player.ID);
            player.MainUnit = unit;
            unit.gameObject.transform.localPosition = new Vector3(30,0,30);
            if (readyPlayer.UserName == playerModel.UserName)
            {
                Game.Scene.Cur<GameScene>().LocalPlayer = player;
                player.OnLoad();
            }
        }
    }

    public static ASTNode _localPlayer(List<ASTNode> args, Context context) 
    {
        return new ObjectNode(Game.Scene.Cur<GameScene>().LocalPlayer);
    }

    public static ASTNode _player_main_unit(List<ASTNode> args, Context context) 
    {
        args[0] = RT.Evaluate(args[0],context);
        GamePlayer player = (GamePlayer)((ObjectNode)args[0]).Val;
        return new ObjectNode(player.MainUnit);
    }
    #region unit
    public static ASTNode _move_unit(List<ASTNode> args, Context context) 
    {
        args = EvalArgs(args,context);
        Unit unit = (Unit)((ObjectNode)args[0]).Val;
        Vector3 v3 = (Vector3)((ObjectNode)args[1]).Val;
        unit.transform.position = v3;
        return null;
    }
    public static ASTNode _revive_unit(List<ASTNode> args,Context context) 
    {
        args = EvalArgs(args,context);
        Unit unit = (Unit)((ObjectNode)args[0]).Val;
        unit.HP = unit.MaxHP;
        unit.MP = unit.MaxMP;
        unit.IsDie = false;
        unit.CallEvent("UnitCreate");
        return null;
    }
    public static ASTNode _trigger_unit(List<ASTNode> args,Context context) 
    {
       Unit triggerUnit = (Unit)((ObjectNode)context.Find("TriggerUnit")).Val;
       return new ObjectNode(triggerUnit);
    }
    /// <summary>
    /// 0 玩家 1 单位 2 偏移坐标
    /// </summary>
    /// <param name="args"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    public static ASTNode _lock_camera_to_unit(List<ASTNode> args, Context context) 
    {
        args = EvalArgs(args,context);
        GamePlayer gamePlayer = (GamePlayer)((ObjectNode)args[0]).Val;
        Unit unit = (Unit)((ObjectNode)args[1]).Val;
        Vector3 OffsetPos = (Vector3)((ObjectNode)args[2]).Val;
        gamePlayer.mCamera.LockToUnit(unit, OffsetPos);
        return null;
    }

    public static ASTNode _unit_attr(List<ASTNode> args,Context context) 
    {
        args = EvalArgs(args,context);
        Unit unit = (Unit)((ObjectNode)args[0]).Val;
        string attrType = ((StringNode)args[1]).Val;
        switch(attrType)
        {
            case "HP":
                NumberNode HPNode = new NumberNode();
                HPNode.NumberVal = unit.HP;
                HPNode.Type = NumberNode.NumberType.INT;
                return HPNode;
            case "MaxHP":
                NumberNode MaxHPNode = new NumberNode();
                MaxHPNode.NumberVal = unit.MaxHP;
                MaxHPNode.Type = NumberNode.NumberType.INT;
                return MaxHPNode;
            case "MP":
                NumberNode MPNode = new NumberNode();
                MPNode.NumberVal = unit.MP;
                MPNode.Type = NumberNode.NumberType.INT;
                return MPNode;
            case "MaxMP":
                NumberNode MaxMPNode = new NumberNode();
                MaxMPNode.NumberVal = unit.MaxMP;
                MaxMPNode.Type = NumberNode.NumberType.INT;
                return MaxMPNode;
        }
        return null;
    }

    public static ASTNode _unit_flag(List<ASTNode> args, Context context) 
    {
        args = EvalArgs(args,context);
        Unit unit  = (Unit)((ObjectNode)args[0]).Val;
        string flagkey = ((StringNode)args[1]).Val;
        return new BoolNode(unit.GetFlag(flagkey));
    }
    #endregion

    #region actor
    public static ASTNode _set_actor_pos(List<ASTNode> args, Context context) 
    {
        args = EvalArgs(args,context);
        Actor actor = (Actor)((ObjectNode)args[0]).Val;
        actor.ActorGameObject.transform.localPosition = (Vector3)((ObjectNode)args[1]).Val;
        return null;
    }

    public static ASTNode _player_anim(List<ASTNode> args, Context context)
    {
        string animName = ((StringNode)args[0]).Val;
        Actor node = (Actor)((ObjectNode)context.Find("self-actor")).Val;
        Animation anim = node.ActorGameObject.GetComponent<Animation>();
      
        Animator animr = node.ActorGameObject.GetComponent<Animator>();
        animr.SetTrigger(animName);
        return null;
    }

    public static ASTNode _actor_attr(List<ASTNode> args,Context context) 
    {
        args = EvalArgs(args,context);
        Actor actor = (Actor)((ObjectNode)args[0]).Val;
        string attrType = ((StringNode)args[1]).Val;
        switch (attrType) 
        {
            case "GameObject":
                return new ObjectNode(actor.ActorGameObject);
        }
        return null;
    }
    #endregion
    
    public static ASTNode _UnitPlayerName(List<ASTNode> args, Context context) 
    {
        args = EvalArgs(args,context);
        Unit unit =(Unit)((ObjectNode)args[0]).Val;
        StringNode node = new StringNode();
        GamePlayer player = Game.Scene.Cur<GameScene>().GamePlayers[unit.GamePlayerId];
        node.Val = player.UserName;
        return node;
    }

    #region NGUI
    public static ASTNode _set_label_text(List<ASTNode> args, Context context) 
    {
       args = EvalArgs(args,context);
       Actor actor = (Actor)((ObjectNode)args[0]).Val;
       actor.ActorGameObject.GetComponent<UILabel>().text = ((StringNode)args[1]).Val;
       return null;
    }
    
    public static  ASTNode _set_label_color(List<ASTNode> args,Context context)
    {
      args = EvalArgs(args,context);
      Actor actor = (Actor)((ObjectNode)args[0]).Val;
      Color color = (Color)((ObjectNode)args[1]).Val;
      actor.ActorGameObject.GetComponent<UIWidget>().color = color;
      return null;
    }

    public static ASTNode _sprite_attr(List<ASTNode> args,Context context) 
    {
        args = EvalArgs(args,context);
        UISprite spr =  ((GameObject)((ObjectNode)args[0]).Val).GetComponent<UISprite>();
        string strType = ((StringNode)args[1]).Val;
        switch (strType) 
        {
            case "fillAmount":
                spr.fillAmount =(float)((NumberNode)args[2]).NumberVal;
            break;
        }
        return null;
    }
    #endregion
    public static ASTNode _findG(List<ASTNode> args,Context context) 
    {
        args = EvalArgs(args,context);

        GameObject CurG = (GameObject)((ObjectNode)args[0]).Val;
        string path =  ((StringNode)args[1]).Val;
        Transform FindT = CurG.transform.Find(path);
        if (FindT == null)
        {
            return new ObjectNode(null);
        }
        else 
        {
            return new ObjectNode(FindT.gameObject);
        }
    }

}
